#pragma once
namespace zh 
{
	template<class T>
	struct __list_node
	{
		typedef __list_node<T> Node;
	public:

		__list_node(const T& t=T())
			:_prev(nullptr)
			, _next(nullptr)
			, _data(t)
		{}

		T& operator*()
		{
			return (*this)._data;
		}

		//__list_node& operator++(void)
		//{
		//	this->_prev = this;
		//	this = this->_next;
		//	this->_next = this->_next;
		//	return *this;
		//}

		Node* _prev;
		T _data;
		Node* _next;
	};

	template<class T, class Ref, class Ptr>
	struct __list_iterator
	{
		typedef __list_node<T> Node;
	public:
		typedef __list_iterator<T, Ref, Ptr> Self;

		__list_iterator(Node* Node)
			:_node(Node)
		{}

		Ref operator*()
		{
			return _node->_data;
		}

		Ptr operator->()
		{
			return &(_node->_data);
		}

		Self& operator++(void)
		{
			_node = _node->_next;
			return *this;
		}

		Self operator++(int)
		{
			Node* tmp(_node->_data);
			_node = _node->_next;
			return tmp;
		}

		Self& operator--(void)
		{
			_node = _node->_prev;
			return *this;
		}

		Self operator--(int)
		{
			Node* tmp(_node->_data);
			_node = _node->_prev;
			return tmp;
		}

		bool operator==(const Self& it)
		{
			return _node == it._node;
		}

		bool operator!=(const Self& it)
		{
			return _node != it._node;
		}

		~__list_iterator()
		{
			_node = nullptr;
		}
		Node* _node;
	};

	template<class T>
	class list
	{
		typedef __list_node<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;

		iterator begin()
		{
			return (iterator)_head->_next;
		}

		iterator end()
		{
			return (iterator)_head;
		}

		const_iterator begin() const
		{
			return (const_iterator)_head->_next;
		}

		const_iterator end() const
		{
			return (const_iterator)_head;
		}

		iterator cbegin()
		{
			return (iterator)_head->_prev;
		}

		iterator cend()
		{
			return (iterator)_head;
		}

		const_iterator cbegin() const
		{
			return (const_iterator)_head->_prev;
		}

		const_iterator cend() const
		{
			return (const_iterator)_head;
		}

		list()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}

		list(const list<T>& t)
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;

			for (auto e : t)
				push_back(e);
		}

		void push_front(const T& t)
		{
			insert(begin(), t);
		}

		void push_back(const T& t)
		{
			//Node* newNode = new Node;
			//newNode->_data = t;
			//Node* tail = _head->_prev;

			//tail->_next = newNode;
			//_head->_prev = newNode;
			//newNode->_prev = tail;
			//newNode->_next = _head;
			insert(end(), t);
		}

		void pop_back()
		{
			erase(--end());
		}

		void pop_front()
		{
			erase(begin());
		}

		void insert(const iterator& pos,const T& lt)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* newnode = new Node(lt);
			*newnode = lt;

			prev->_next = newnode;
			newnode->_next = cur;
			cur->_prev = newnode;
			newnode->_prev = prev;
		}

		void erase(iterator& pos, size_t n = 1)
		{
			if (pos == end())
				exit(-1);

			while (n > 0)
			{
				if (pos != end())
				{
					Node* cur = pos._node;
					Node* prev = cur->_prev;
					Node* next = cur->_next;
					prev->_next = next;
					next->_prev = prev;

					++pos;

					delete cur;
					cur = nullptr;

				}
				else
				{break;}
				--n;
			}
		}

		list<T>& operator=(list<T> lt)
		{
			swap(_head, lt._head);
			return *this;
		}

		list<T>& operator=(const list<T>& lt)
		{
			auto it = lt.begin();
			if (this != &it)
			{
				//::clear();
				for (auto e : it)
				{
					push_back(e);
				}
				return *this;
			}
		}

		void clear()
		{
			iterator it = begin();
			erase(it,-1);
		}

		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
	private:
		Node* _head;
	};

	class Date
	{
	public:
		Date(int year = 0, int month = 1, int day = 1)
			:_year(year)
			, _month(month)
			, _day(day)
		{}
		int _year;
		int _month;
		int _day;
	};
}
